package com.example.voting_master.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.voting_master.constant.RedisConstant;
import com.example.voting_master.entity.VoteTheme;
import com.example.voting_master.mapper.VoteThemeMapper;
import com.example.voting_master.service.VoteThemeService;
import com.example.voting_master.util.RedisCacheUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static com.example.voting_master.constant.RedisConstant.Theme;
import static com.example.voting_master.constant.RedisConstant.Visits;

@Service
public class VoteThemeServiceImpl extends ServiceImpl<VoteThemeMapper, VoteTheme>
        implements VoteThemeService{
    @Resource
    private VoteThemeMapper voteThemeMapper;
    @Resource
    private RedisCacheUtil redisCacheUtil;

    @Override
    public List<VoteTheme> showAll(){
        //1、分开存储为hash
        /*List<VoteTheme> votes;

        //用于存储缓存的键前缀
        String redisKey = RedisConstant.Theme + "all:";

        //获取themeAll的所有key
        Set<String> keys = redisCacheUtil.hKey(redisKey + "*");
        //从redis找缓存
        List<JSONObject> themeAll = new ArrayList<>();
        for (String key:keys) {
            Map<Object,Object> value = redisCacheUtil.hmget(key);
            JSONObject valueTemp = JSONObject.parseObject(JSON.toJSONString(value));
            System.out.println(valueTemp);
            themeAll.add(valueTemp);
            System.out.println(themeAll);
        }

        if(themeAll.isEmpty()){
            votes = voteThemeMapper.selectVoteThemeWithCandidates();
            //存哈希
            for (VoteTheme voteTheme:votes) {
                Map<String, Object> voteMap = BeanUtil.beanToMap(voteTheme);
                String mapId = voteTheme.getId().toString();
                redisCacheUtil.hmset(redisKey +  mapId,voteMap);
            }
        }
        else {
            String ThemeAllTemp = themeAll.toString();
            votes = JSONArray.parseArray(ThemeAllTemp,VoteTheme.class);
        }

        return votes;*/

        //2、直接包装成String
        List<VoteTheme> votes;
        List<VoteTheme> themeAll = new ArrayList<>();
        String redisKey = Theme + "all:";

        //获取Theme:all:下所有keys
        Set<String> keys = redisCacheUtil.hKey(redisKey + "*");
        for (String key:keys) {
            Object theme = redisCacheUtil.get(key);
            if(theme != null) {
                VoteTheme voteTheme = JSONObject.parseObject(theme.toString(), VoteTheme.class);
                themeAll.add(voteTheme);
            }
            System.out.println(theme);
            System.out.println(key);
        }

        System.out.println(themeAll);

        if(themeAll.isEmpty()){
            votes = voteThemeMapper.selectVoteThemeWithCandidates();
            for (VoteTheme vote:votes) {
                String votesTemp = JSON.toJSONString(vote);
                redisCacheUtil.set(redisKey + vote.getId(),votesTemp);
            }
        }
        else {
            /*String ThemeAllTemp = themeAll.toString();
            votes = JSONArray.parseArray(ThemeAllTemp,VoteTheme.class);*/
            votes = themeAll;
        }

        return votes;
    }

    @Override
    public Boolean visitIncrement(Long id) {
        // 数据校验
        if (id == null)
            return false;

        // 读redis，判断对应投票活动的访问量是否存在
        String redisKey = Theme + Visits + id;
        Object redisResult = redisCacheUtil.get(redisKey);
        if(redisResult == null) {
            // 不存在时从数据库中读取
            VoteTheme voteTheme = voteThemeMapper.selectById(id);
            // 校验查询的数据
            if(voteTheme != null) {
                // 将查询到的数据访问量自增并存入redis
                redisCacheUtil.set(redisKey,voteTheme.getTotalVisits()+1);
            }else   // 数据库也不存在的场合，返回false
                return false;
        }else {
            // 存在时使其自增+1
            redisCacheUtil.incr(redisKey,1L);
        }
        return true;
    }

    /**
     * 根据redis的theme:visits:下的存储更新数据库主题表每个主题的total_visits
     */
    @Override
    public void fromRedisUpdateAllThemeVisits(){

        //获取所有theme对应的total_visits的key
        Set<String > visitsKeys = redisCacheUtil.hKey(RedisConstant.Theme + RedisConstant.Visits + "*");
        //作为更新的载体
        VoteTheme voteTheme = new VoteTheme();
        for (String visitsKey:visitsKeys) {
            //获取主题id
            String id_str = visitsKey.split(":")[2];
            Long themeId = Long.parseLong(id_str);
            //获取对应theme的visits的value
            Object redisResult = redisCacheUtil.get(visitsKey);
            Long visit;
            if(redisResult != null){
                visit = Long.parseLong(redisResult.toString());
                //存入载体
                voteTheme.setTotalVisits(visit);
                //条件构造器
                LambdaUpdateWrapper<VoteTheme> lambdaUpdateWrapper = new UpdateWrapper<VoteTheme>().lambda();
                lambdaUpdateWrapper.eq(VoteTheme::getId,themeId);

                voteThemeMapper.update(voteTheme,lambdaUpdateWrapper);
            }
        }
    }

    /**
     *更新theme:all:下的主题缓存
     */
    @Override
    public void updateAllThemeForRedis(){

        //获取key
        String redisKey = RedisConstant.Theme + "all:";
        //更新redis的theme:all缓存
        boolean a = false;
        List<VoteTheme> votes = voteThemeMapper.selectVoteThemeWithCandidates();
        for (VoteTheme vote:votes) {
            String votesTemp = JSON.toJSONString(vote);
            a = redisCacheUtil.set(redisKey + vote.getId(),votesTemp);
        }
        System.out.println(a);
    }
}
